/*
 * RMatrix4d.java -
 * Copyright (c) 2005 Carmine Lia
 * e-mail:      carmine.lia@libero.it
 * web-address: http://www.intermedia.sa.it/lia

 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
package javax.robotics.vecmath;

import java.io.PrintStream;
import java.util.Locale;

import javax.vecmath.Matrix4d;

/**
 * A double precision floating point 4 by 4 matrix. Primarily to support 3D
 * rotations and translations. This class extends printing functionality of
 * Matrix4d class
 * 
 * @author <a href="http://www.intermedia.sa.it/lia/">Carmine Lia</a>
 * @since 1.0.1
 * @version 5/10/2005
 */
public class RMatrix4d extends Matrix4d
{

    /**
     * 
     */
    private static final long serialVersionUID = 3257849887369475128L;
    private static final String strLineSeparator = "line.separator";
    private static final String newLine = System.getProperty(strLineSeparator);
    private static final String formatString = "%9.4f ";

    /**
     * Constructs a new matrix with the same values as the Matrix4d parameter.
     * 
     * @param matrix
     *            the source matrix
     */
    public RMatrix4d(Matrix4d matrix)
    {
        super(matrix);
    }

    /**
     * Constructs a new matrix with the same values as the RMatrix4d parameter.
     * 
     * @param matrix
     *            the source matrix
     */
    public RMatrix4d(RMatrix4d matrix)
    {
        super(matrix);
    }

    /**
     * Constructs and initializes a Matrix4d to all zeros.
     */
    public RMatrix4d()
    {
        super();
    }

    /**
     * Constructs and initializes a Matrix4d from the specified 16 element
     * array. this.m00 =matrix[0], this.m01=matrix[1], ... , this.m10=matrix[4],
     * etc.
     * 
     * @param matrix
     *            the array of length 16 containing in order
     */
    public RMatrix4d(double[] matrix)
    {
        super(matrix);
    }

    /**
     * Constructs and initializes a RMatrix4f from the rotation matrix,
     * translation, and scale values; the scale is applied only to the
     * rotational components of the matrix (upper 3x3) and not to the
     * translational components of the matrix.
     * 
     * @param rot
     *            the rotation matrix representing the rotational components
     * @param tr
     *            the translational components of the matrix
     * @param s
     *            the scale value applied to the rotational components
     */
    public RMatrix4d(RMatrix3d rot, RVector3d tr, double s)
    {
        super(rot, tr, s);
    }

    /**
     * Constructs and initializes a RMatrix4d from the quaternion, translation,
     * and scale values; the scale is applied only to the rotational components
     * of the matrix (upper 3x3) and not to the translational components.
     * 
     * @param rot
     *            the quaternion value representing the rotational component
     * @param tr
     *            the translational components of the matrix
     * @param s
     *            the scale value applied to the rotational components
     */
    public RMatrix4d(Quaternion rot, RVector3d tr, double s)
    {
        super(rot, tr, s);
    }

    /**
     * Prints to standard out
     */
    public void printf()
    {
        this.printf(System.out, formatString);
   }

    /**
     * Prints to standard out according to the format string.
     * <p>
     * The format specifiers for numeric types have the following syntax:
     * 
     * <pre>%[width][.precision]conversion</pre>
     * 
     * <ul>
     * <li> The optional <b><code>width</code></b> is a non-negative decimal
     * integer indicating the minimum number of characters to be written to the
     * output. </li>
     * <li> The optional <b><code>precision</code></b> is a non-negative
     * decimal integer usually used to restrict the number of characters. The
     * specific behavior depends on the conversion. </li>
     * <li> The required <b><code>conversion</code></b> is a character
     * indicating how the argument should be formatted. The set of valid
     * conversions for a given argument depends on the argument's data type.
     * </li>
     * </ul>
     * <p>
     * Example: </br><code>v.printf("%5.3f");</code>
     * </p>
     * 
     * @param format
     *            The format string
     * @see PrintStream#format(java.lang.String, java.lang.Object[])
     */
    public void printf(String format)
    {
        this.printf(System.out, format);
    }

    /**
     * Prints to <code>PrintStream</code>
     * 
     * @param out
     *            The <code>PrintStream</code> object.
     */
    public void printf(PrintStream out)
    {
        this.printf(out, formatString);
    }

    /**
     * Prints to <code>PrintStream</code> according to the format string
     * 
     * @param out
     *            The <code>PrintStream</code> object.
     * @param format
     *            The format string.
     * @see #printf(String)
     */
    public void printf(PrintStream out, String format)
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
                out.printf(Locale.US, format, this.getElement(i, j));
            out.println(newLine);
        }
    }

    /**
     * Returns a string that contains the values of this RVector.
     * 
     * @return The string.
     */
    public String toString()
    {
         return this.toString(formatString);
    }

    /**
     * Returns a string that contains the values of this RVector, according to
     * the format string
     * 
     * @param format
     *            The format string
     * @return The string
     * @see #printf(String)
     */
    public String toString(String format)
    {

        final StringBuffer buffer = new StringBuffer(128);

        int i, j;

        for (i = 0; i < 4; i++)
        {
            for (j = 0; j < 4; j++)
            {
                buffer.append(String.format(Locale.US, format, this.getElement(i, j)));
                // .append(" ");
            }
            buffer.append(newLine);
        }

        return buffer.toString();
    }
    
    /**
     * Gets this matrix as mono dimensional array
     * 
     * @param matrix
     *            the array
     */
    public void get(double[] matrix)
    {
        // first row
        matrix[0]= this.m00;
        matrix[1]= this.m01;
        matrix[2]= this.m02;
        matrix[3]= this.m03;
        
        // 2nd row
        matrix[4]= this.m10;
        matrix[5]= this.m11;
        matrix[6]= this.m12;
        matrix[7]= this.m13;
        
        // 3rd row
        matrix[8] = this.m20;
        matrix[9] = this.m21;
        matrix[10]= this.m22;
        matrix[11]= this.m23;
        
        // 4th row
        matrix[12]= this.m30;
        matrix[13]= this.m31;
        matrix[14]= this.m32;
        matrix[15]= this.m33;
     }
   
}
